home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d927.lha / Ftp / src / ftp.c < prev    next >
C/C++ Source or Header  |  1993-10-07  |  39KB  |  1,944 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)ftp.c    5.28 (Berkeley) 4/20/89";
  20. #endif /* not lint */
  21.  
  22. #include <sys/param.h>
  23. #include <sys/stat.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/socket.h>
  26. #ifdef AMI_TCP
  27. #include <bsdsocket.h>
  28. #include <dos/dos.h>
  29. #else
  30. #include <ss/socket.h>
  31. #endif
  32. #include <sys/time.h>
  33. #ifndef AMI_TCP
  34. #include <sys/file.h>
  35. #endif
  36.  
  37. #include <netinet/in.h>
  38. #include <arpa/ftp.h>
  39. #include <arpa/telnet.h>
  40.  
  41. #include <stdio.h>
  42. #include <signal.h>
  43. #include <errno.h>
  44. #include <netdb.h>
  45. #include <fcntl.h>
  46. #ifndef AMI_TCP
  47. #include <pwd.h>
  48. #endif
  49. //#include <syslog.h>
  50. #include <varargs.h>
  51. #ifdef __SASC
  52. #include <ios1.h>
  53. #endif
  54.  
  55. #include "ftp_var.h"
  56.  
  57. extern int Enable_Abort;
  58.  
  59. #ifndef MAXHOSTNAMELEN
  60. #define MAXHOSTNAMELEN 64
  61. #endif
  62.  
  63. #ifdef NOVFPRINTF
  64. #define vfprintf(a,b,c) _doprnt(b,c,a)
  65. #endif
  66.  
  67. #ifdef sun
  68. /* FD_SET wasn't defined until 4.0. its a cheap test for uid_t  presence */
  69. #ifndef FD_SET
  70. #define    NBBY    8        /* number of bits in a byte */
  71. /*
  72.  * Select uses bit masks of file descriptors in longs.
  73.  * These macros manipulate such bit fields (the filesystem macros use chars).
  74.  * FD_SETSIZE may be defined by the user, but the default here
  75.  * should be >= NOFILE (param.h).
  76.  */
  77. #ifndef    FD_SETSIZE
  78. #define    FD_SETSIZE    256
  79. #endif
  80.  
  81. typedef long    fd_mask;
  82. #define NFDBITS    (sizeof(fd_mask) * NBBY)    /* bits per mask */
  83. #ifndef howmany
  84. #define    howmany(x, y)    (((x)+((y)-1))/(y))
  85. #endif
  86.  
  87. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  88. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  89. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  90. #define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  91.  
  92. typedef int uid_t;
  93. typedef int gid_t;
  94. #endif /* FD_SET */
  95. #endif /*sun */
  96.  
  97. struct    sockaddr_in hisctladdr;
  98. struct    sockaddr_in data_addr;
  99. int    data = -1;
  100. int    abrtflag = 0;
  101. int    ptflag = 0;
  102. int    allbinary;
  103. struct    sockaddr_in myctladdr;
  104. sig_t    lostpeer();
  105. off_t    restart_point = 0;
  106. extern char *home;
  107. extern FILE *log_file;
  108.  
  109. int    cin, cout; /* these are FD's now, not FILE *'s */
  110. int    dataconn();
  111.  
  112. char *
  113. hookup(host, port)
  114.     char *host;
  115.     int port;
  116. {
  117.     register struct hostent *hp = 0;
  118.     int s,len;
  119.     static char hostnamebuf[80];
  120.  
  121.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  122.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  123.     if (hisctladdr.sin_addr.s_addr != -1) {
  124.         hisctladdr.sin_family = AF_INET;
  125.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  126.     } else {
  127.         hp = gethostbyname(host);
  128.         if (hp == NULL) {
  129.             fprintf(stderr, "ftp: %s: ", host);
  130.             herror((char *)NULL);
  131.             code = -1;
  132.             return((char *) 0);
  133.         }
  134.         hisctladdr.sin_family = hp->h_addrtype;
  135.         bcopy(hp->h_addr_list[0],
  136.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  137.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  138.     }
  139.     hostname = hostnamebuf;
  140.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  141.     if (s < 0) {
  142.         perror("ftp: socket");
  143.         code = -1;
  144.         return (0);
  145.     }
  146.     hisctladdr.sin_port = port;
  147.     while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  148.         if (hp && hp->h_addr_list[1]) {
  149.             int oerrno = errno;
  150.  
  151.             fprintf(stderr, "ftp: connect to address %s: ",
  152.                 inet_ntoa(hisctladdr.sin_addr));
  153.             errno = oerrno;
  154.             perror((char *) 0);
  155.             hp->h_addr_list++;
  156.             bcopy(hp->h_addr_list[0],
  157.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  158.             fprintf(stdout, "Trying %s...\n",
  159.                 inet_ntoa(hisctladdr.sin_addr));
  160.             (void) close(s);
  161.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  162.             if (s < 0) {
  163.                 perror("ftp: socket");
  164.                 code = -1;
  165.                 return (0);
  166.             }
  167.             continue;
  168.         }
  169.         perror("ftp: connect");
  170.         code = -1;
  171.         goto bad;
  172.     }
  173.     len = sizeof (myctladdr);
  174.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  175.         perror("ftp: getsockname");
  176.         code = -1;
  177.         goto bad;
  178.     }
  179.     cin = cout = s;
  180.     if (verbose)
  181.         printf("Connected to %s.\n", hostname);
  182.     if (getreply(0) > 2) {     /* read startup message from server */
  183.         code = -1;
  184.         goto bad;
  185.     }
  186. #ifdef SO_OOBINLINE
  187.     {
  188.     int on = 1;
  189.  
  190.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
  191.         < 0 && debug) {
  192.             perror("ftp: setsockopt");
  193.         }
  194.     }
  195. #endif /* SO_OOBINLINE */
  196.  
  197.     return (hostname);
  198. bad:
  199.     (void) s_close(s);
  200.     return ((char *)0);
  201. }
  202.  
  203. login(host)
  204.     char *host;
  205. {
  206.     char tmp[80];
  207.     char *user, *pass, *acct, *getlogin(), *getpass();
  208.     int n, aflag = 0;
  209.     char *myname;
  210.     extern char *mygetenv();
  211.  
  212.     myname = mygetenv("USERNAME");
  213.  
  214.     user = pass = acct = 0;
  215. #if 0
  216.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  217.         code = -1;
  218.         return(0);
  219.     }
  220. #endif
  221.     while (user == NULL) {
  222.                 if (myname)
  223.                         printf("Name (%s:%s): ", host, myname);
  224.                 else
  225.                         printf("Name (%s): ", host);
  226.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  227.         tmp[strlen(tmp) - 1] = '\0';
  228.         if (*tmp == '\0')
  229.             user = myname;
  230.         else
  231.             user = tmp;
  232.     }
  233. #ifdef FTP_LOG_USAGE
  234.     syslog(LOG_INFO, "FTP LOGIN by %s to %s as %s",
  235.            myname ? myname : "unknown", host, user);
  236. #endif /* FTP_LOG_USAGE */
  237.     n = command("USER %s", user);
  238.     if (n == CONTINUE) {
  239.         if (pass == NULL)
  240.             pass = getpass("Password:");
  241.         n = command("PASS %s", pass);
  242.     }
  243.     if (n == CONTINUE) {
  244.         aflag++;
  245.         acct = getpass("Account:");
  246.         n = command("ACCT %s", acct);
  247.     }
  248.     if (n != COMPLETE) {
  249.         fprintf(stderr, "Login failed.\n");
  250.         return (0);
  251.     }
  252.     if (!aflag && acct != NULL)
  253.         (void) command("ACCT %s", acct);
  254.     if (proxy)
  255.         return(1);
  256.     for (n = 0; n < macnum; ++n) {
  257.         if (!strcmp("init", macros[n].mac_name)) {
  258.             (void) strcpy(line, "$init");
  259.             makeargv();
  260.             domacro(margc, margv);
  261.             break;
  262.         }
  263.     }
  264.     return (1);
  265. }
  266.  
  267. #if 0
  268. sig_t
  269. cmdabort()
  270. {
  271.     extern jmp_buf ptabort;
  272.  
  273.     printf("\n");
  274.     (void) fflush(stdout);
  275.     abrtflag++;
  276.     if (ptflag)
  277.         longjmp(ptabort,1);
  278. }
  279. #endif
  280.  
  281. /*VARARGS1*/
  282. command(va_alist)
  283. va_dcl
  284. {
  285.     va_list ap;
  286.     char *fmt;
  287.     int r;
  288. //    sig_t (*oldintr)(), cmdabort();
  289.     int len; char str_buf[256];
  290.  
  291.     abrtflag = 0;
  292.     if (debug) {
  293.         printf("---> ");
  294.         va_start(ap);
  295.         fmt = va_arg(ap, char *);
  296.         vfprintf(stdout, fmt, ap);
  297.         va_end(ap);
  298.         printf("\n");
  299.         (void) fflush(stdout);
  300.     }
  301.     if (cout == -1) {
  302.         perror ("No control connection for command");
  303.         code = -1;
  304.         return (0);
  305.     }
  306. //    oldintr = signal(SIGINT,cmdabort);
  307.     va_start(ap);
  308.     fmt = va_arg(ap, char *);
  309.     len = vsprintf(str_buf, fmt, ap);
  310.     strcpy(&str_buf[len],"\r\n");
  311.     send(cout, str_buf, len+2, 0);
  312.     va_end(ap);
  313.     cpend = 1;
  314.     r = getreply(!strcmp(fmt, "QUIT"));
  315. //    if (abrtflag && oldintr != SIG_IGN)
  316. //        (*oldintr)();
  317. //    (void) signal(SIGINT, oldintr);
  318.     return(r);
  319. }
  320.  
  321. char reply_string[BUFSIZ];        /* last line of previous reply */
  322.  
  323. #include <ctype.h>
  324.  
  325. getreply(expecteof)
  326.     int expecteof;
  327. {
  328.     register int n, c;
  329.     register int dig;
  330.     register char *cp;
  331.     int originalcode = 0, continuation = 0;
  332. //    sig_t (*oldintr)(), cmdabort();
  333.     int pflag = 0;
  334.     char *pt = pasv;
  335.     char str_buf[8];
  336.  
  337. //    oldintr = signal(SIGINT,cmdabort);
  338.     for (;;) {
  339.         dig = n = code = 0;
  340.         cp = reply_string;
  341.         while ((c = sgetc(cin)) != '\n') {
  342.             if (c == IAC) {     /* handle telnet commands */
  343.                 switch (sgetc(cin)) {
  344.                 case WILL:
  345.                 case WONT:
  346.                     str_buf[0] = IAC; str_buf[1] = DONT;
  347.                     str_buf[2] = sgetc(cin);
  348.                     send(cout, str_buf, 3, 0);
  349.                     break;
  350.                 case DO:
  351.                 case DONT:
  352.                     str_buf[0] = IAC; str_buf[1] = DONT;
  353.                     str_buf[2] = sgetc(cin);
  354.                     send(cout, str_buf, 3, 0);
  355.                     break;
  356.                 default:
  357.                     break;
  358.                 }
  359.                 continue;
  360.             }
  361.             dig++;
  362.             if (c == EOF) {
  363.                 if (expecteof) {
  364. //                    (void) signal(SIGINT,oldintr);
  365.                     code = 221;
  366.                     return (0);
  367.                 }
  368.                 lostpeer();
  369.                 if (verbose) {
  370.                     printf("421 Service not available, remote server has closed connection\n");
  371.                     (void) fflush(stdout);
  372.                 }
  373.                 code = 421;
  374.                 return(4);
  375.             }
  376.             if (c != '\r' && (verbose > 0 ||
  377.                 (verbose > -1 && n == '5' && dig > 4))) {
  378.                 if (proxflag &&
  379.                    (dig == 1 || dig == 5 && verbose == 0))
  380.                     printf("%s:",hostname);
  381.                 (void) putchar(c);
  382.             }
  383.             if (dig < 4 && isdigit(c))
  384.                 code = code * 10 + (c - '0');
  385.             if (!pflag && code == 227)
  386.                 pflag = 1;
  387.             if (dig > 4 && pflag == 1 && isdigit(c))
  388.                 pflag = 2;
  389.             if (pflag == 2) {
  390.                 if (c != '\r' && c != ')')
  391.                     *pt++ = c;
  392.                 else {
  393.                     *pt = '\0';
  394.                     pflag = 3;
  395.                 }
  396.             }
  397.             if (dig == 4 && c == '-') {
  398.                 if (continuation)
  399.                     code = 0;
  400.                 continuation++;
  401.             }
  402.             if (n == 0)
  403.                 n = c;
  404.             if (cp < &reply_string[sizeof(reply_string) - 1])
  405.                 *cp++ = c;
  406.         }
  407.         if (verbose > 0 || verbose > -1 && n == '5') {
  408.             (void) putchar(c);
  409.             (void) fflush (stdout);
  410.         }
  411.         if (continuation && code != originalcode) {
  412.             if (originalcode == 0)
  413.                 originalcode = code;
  414.             continue;
  415.         }
  416.         *cp = '\0';
  417.         if (n != '1')
  418.             cpend = 0;
  419. //        (void) signal(SIGINT,oldintr);
  420.         if (code == 421 || originalcode == 421)
  421.             lostpeer();
  422. //        if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  423. //            (*oldintr)();
  424.         return (n - '0');
  425.     }
  426. }
  427.  
  428. empty(mask, sec)
  429.     struct fd_set *mask;
  430.     int sec;
  431. {
  432.     struct timeval t;
  433.  
  434.     t.tv_sec = (long) sec;
  435.     t.tv_usec = 0;
  436.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  437. }
  438.  
  439. jmp_buf    sendabort;
  440.  
  441. abortsend()
  442. {
  443.  
  444.     mflag = 0;
  445.     abrtflag = 0;
  446.     printf("\nsend aborted\n");
  447.     (void) fflush(stdout);
  448.     longjmp(sendabort, 1);
  449. }
  450.  
  451. char *basename(char *fname)
  452. {
  453. static const char delim[] = ":/]\\";
  454.  
  455.     const char *p;
  456.     char *fn;
  457.  
  458.     for (fn = &fname[strlen(fname)]; --fn >= fname;)
  459.     {    for (p = delim; *p; p++)
  460.         {    if (*fn == *p) break;
  461.             if (*fn == ';') *fn = 0;    /* strip VMS version no. */
  462.         }
  463.         if (*p) break;
  464.     }
  465.     if (fn >= fname) return fn+1;
  466.     return fname;
  467. }
  468.  
  469. #define HASHBYTES 1024
  470. char buf[BUFSIZ];
  471.  
  472. sendrequest(cmd, local, remote, printnames)
  473.     char *cmd, *local, *remote;
  474.     int printnames;
  475. {
  476.     FILE *fin;
  477.     int dout;
  478.     int (*closefunc)(), fclose();
  479. //    sig_t (*oldintr)(), (*oldintp)();
  480.     int abortsend();
  481.     char *bufp;
  482.     long bytes = 0, hashbytes = HASHBYTES;
  483.     register int c, d;
  484.     struct stat st;
  485.     struct timeval start, stop;
  486.     char *mode;
  487.     char real_local[128];
  488.  
  489.     if (local[0] != '-')
  490.     {    joinpath(real_local,uldir,basename(local));
  491.         local = real_local;
  492.     }
  493.  
  494.     if (verbose && printnames) {
  495.         if (local && *local != '-')
  496.             printf("local: %s ", local);
  497.         if (remote)
  498.             printf("remote: %s\n", remote);
  499.     }
  500.     if (proxy) {
  501.         proxtrans(cmd, local, remote);
  502.         return;
  503.     }
  504.     closefunc = NULL;
  505. //    oldintr = NULL;
  506. //    oldintp = NULL;
  507.     mode = "w";
  508.     if (setjmp(sendabort)) {
  509.         while (cpend) {
  510.             (void) getreply(0);
  511.         }
  512.         if (data >= 0) {
  513.             (void) s_close(data);
  514.             data = -1;
  515.         }
  516. //        if (oldintr)
  517. //            (void) signal(SIGINT,oldintr);
  518. //        if (oldintp)
  519. //            (void) signal(SIGPIPE,oldintp);
  520.         code = -1;
  521.         return;
  522.     }
  523. //    oldintr = signal(SIGINT, abortsend);
  524.     if (strcmp(local, "-") == 0)
  525.         fin = stdin;
  526. #if 0
  527.     else if (*local == '|') {
  528.         oldintp = signal(SIGPIPE,SIG_IGN);
  529.         fin = popen(local + 1, "r");
  530.         if (fin == NULL) {
  531.             perror(local + 1);
  532.             (void) signal(SIGINT, oldintr);
  533.             (void) signal(SIGPIPE, oldintp);
  534.             code = -1;
  535.             return;
  536.         }
  537.         closefunc = pclose;
  538.     }
  539. #endif
  540.     else
  541.     {
  542.         fin = fopen(local, "r");
  543.         if (fin == NULL) {
  544.             perror(local);
  545. //            (void) signal(SIGINT, oldintr);
  546.             code = -1;
  547.             return;
  548.         }
  549.         closefunc = fclose;
  550. #if 0
  551.         if (fstat(fileno(fin), &st) < 0 ||
  552.             (st.st_mode&S_IFMT) != S_IFREG) {
  553.             fprintf(stdout, "%s: not a plain file.\n", local);
  554.             (void) signal(SIGINT, oldintr);
  555.             fclose(fin);
  556.             code = -1;
  557.             return;
  558.         }
  559. #endif
  560.     }
  561.     if (initconn()) {
  562. //        (void) signal(SIGINT, oldintr);
  563. //        if (oldintp)
  564. //            (void) signal(SIGPIPE, oldintp);
  565.         code = -1;
  566.         if (closefunc != NULL)
  567.             (*closefunc)(fin);
  568.         return;
  569.     }
  570.     if (setjmp(sendabort))
  571.         goto abort;
  572.  
  573. #ifdef __SASC
  574.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  575. #else
  576.     SetMode(_devtab[fileno(stdin)].fd,1L);
  577. #endif
  578.     Enable_Abort = 0;
  579.  
  580.     if (restart_point &&
  581.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  582.         if (fseek(fin, (long) restart_point, 0) < 0) {
  583.             perror(local);
  584.             restart_point = 0;
  585.             if (closefunc != NULL)
  586.                 (*closefunc)(fin);
  587. #ifdef __SASC
  588.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  589. #else
  590.             SetMode(_devtab[fileno(stdin)].fd,0L);
  591. #endif
  592.             Enable_Abort = 1;
  593.             return;
  594.         }
  595.         if (command("REST %ld", (long) restart_point)
  596.             != CONTINUE) {
  597.             restart_point = 0;
  598.             if (closefunc != NULL)
  599.                 (*closefunc)(fin);
  600. #ifdef __SASC
  601.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  602. #else
  603.             SetMode(_devtab[fileno(stdin)].fd,0L);
  604. #endif
  605.             Enable_Abort = 1;
  606.             return;
  607.         }
  608.         restart_point = 0;
  609.         mode = "r+w";
  610.     }
  611.     if (remote) {
  612.         if (command("%s %s", cmd, remote) != PRELIM) {
  613. //            (void) signal(SIGINT, oldintr);
  614. //            if (oldintp)
  615. //                (void) signal(SIGPIPE, oldintp);
  616.             if (closefunc != NULL)
  617.                 (*closefunc)(fin);
  618. #ifdef __SASC
  619.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  620. #else
  621.             SetMode(_devtab[fileno(stdin)].fd,0L);
  622. #endif
  623.             Enable_Abort = 1;
  624.             return;
  625.         }
  626.     } else
  627.         if (command("%s", cmd) != PRELIM) {
  628. //            (void) signal(SIGINT, oldintr);
  629. //            if (oldintp)
  630. //                (void) signal(SIGPIPE, oldintp);
  631.             if (closefunc != NULL)
  632.                 (*closefunc)(fin);
  633. #ifdef __SASC
  634.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  635. #else
  636.             SetMode(_devtab[fileno(stdin)].fd,0L);
  637. #endif
  638.             Enable_Abort = 1;
  639.             return;
  640.         }
  641.     dout = dataconn(mode);
  642.     if (dout == -1)
  643.         goto abort;
  644.     (void) mygettimeofday(&start, (struct timezone *)0);
  645. //    oldintp = signal(SIGPIPE, SIG_IGN);
  646.     switch (type) {
  647.  
  648.     case TYPE_I:
  649.     case TYPE_L:
  650.     case TYPE_A:
  651.         errno = d = 0;
  652.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  653.             bytes += c;
  654.             for (bufp = buf; c > 0; c -= d, bufp += d)
  655.                 if ((d = send(dout, bufp, c, 0)) <= 0)
  656.                     break;
  657.             if (hash) {
  658.                 while (bytes >= hashbytes) {
  659.                     (void) putchar('#');
  660.                     hashbytes += HASHBYTES;
  661.                 }
  662.                 (void) fflush(stdout);
  663.             }
  664. #ifdef __SASC
  665.             if (WaitForChar(chkufb(fileno(stdin))->ufbfh, 0L) == DOSTRUE)
  666. #else
  667.             if (WaitForChar(_devtab[fileno(stdin)].fd, 0L) == DOSTRUE)
  668. #endif
  669.                 goto abort;
  670.             if (SetSignal (0L,SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) goto abort;
  671.         }
  672.         if (hash && bytes > 0) {
  673.             if (bytes < HASHBYTES)
  674.                 (void) putchar('#');
  675.             (void) putchar('\n');
  676.             (void) fflush(stdout);
  677.         }
  678.         if (c < 0)
  679.             perror(local);
  680.         if (d <= 0) {
  681.             if (d == 0)
  682.                 fprintf(stderr, "netout: write returned 0?\n");
  683.             else if (errno != EPIPE) 
  684.                 perror("netout");
  685.             bytes = -1;
  686.         }
  687.         break;
  688.  
  689. #if 0
  690.     case TYPE_A:
  691.         while ((c = getc(fin)) != EOF) {
  692.             if (c == '\n') {
  693.                 while (hash && (bytes >= hashbytes)) {
  694.                     (void) putchar('#');
  695.                     (void) fflush(stdout);
  696.                     hashbytes += HASHBYTES;
  697.                 }
  698.                 if (ferror(dout))
  699.                     break;
  700.                 send(dout, "\r", 1, 0);
  701.                 bytes++;
  702.             }
  703.             send(dout, &c, 1, 0);
  704.             bytes++;
  705.     /*        if (c == '\r') {                  */
  706.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  707.     /*            bytes++;                */
  708.     /*        }                                      */    
  709.         }
  710.         if (hash) {
  711.             if (bytes < hashbytes)
  712.                 (void) putchar('#');
  713.             (void) putchar('\n');
  714.             (void) fflush(stdout);
  715.         }
  716.         if (ferror(fin))
  717.             perror(local);
  718.         if (ferror(dout)) {
  719.             if (errno != EPIPE)
  720.                 perror("netout");
  721.             bytes = -1;
  722.         }
  723.         break;
  724. #endif
  725.     }
  726.     (void) mygettimeofday(&stop, (struct timezone *)0);
  727.     if (closefunc != NULL)
  728.         (*closefunc)(fin);
  729.     s_close(dout);
  730.     (void) getreply(0);
  731. //    (void) signal(SIGINT, oldintr);
  732. //    if (oldintp)
  733. //        (void) signal(SIGPIPE, oldintp);
  734.     if (bytes > 0)
  735. #ifdef FTP_LOG_USAGE
  736.         ptransfer("sent", bytes, &start, &stop, local);
  737. #else
  738.     {   ptransfer("sent", bytes, &start, &stop);
  739.         fprintf(log_file,"%s %d\n",hostname, bytes);
  740.     }
  741. #endif /* FTP_LOG_USAGE */
  742. #ifdef __SASC
  743.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  744. #else
  745.     SetMode(_devtab[fileno(stdin)].fd,0L);
  746. #endif
  747.     Enable_Abort = 1;
  748.     return;
  749. abort:
  750.     (void) mygettimeofday(&stop, (struct timezone *)0);
  751. //    (void) signal(SIGINT, oldintr);
  752. //    if (oldintp)
  753. //        (void) signal(SIGPIPE, oldintp);
  754.     if (!cpend) {
  755.         code = -1;
  756.         return;
  757.     }
  758.     if (data >= 0) {
  759.         (void) s_close(data);
  760.         data = -1;
  761.     }
  762.     dout = -1;
  763.     (void) getreply(0);
  764.     code = -1;
  765.     if (closefunc != NULL && fin != NULL)
  766.         (*closefunc)(fin);
  767.     if (bytes > 0)
  768. #ifdef FTP_LOG_USAGE
  769.         ptransfer("sent", bytes, &start, &stop, local);
  770. #else
  771.     {   ptransfer("sent", bytes, &start, &stop);
  772.         fprintf(log_file,"%s %d\n",hostname, bytes);
  773.     }
  774. #endif /* FTP_LOG_USAGE */
  775. #ifdef __SASC
  776.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  777. #else
  778.     SetMode(_devtab[fileno(stdin)].fd,0L);
  779. #endif
  780.     Enable_Abort = 1;
  781. }
  782.  
  783. display_temp(FILE *fp)
  784. {    char command[128];
  785.     char fname[128];
  786.     char *pager;
  787.  
  788.     fclose(fp); /* This looks stupid, but it's correct */
  789.     if ((pager = mygetenv("PAGER")) == 0)
  790.         pager = "more";
  791.     joinpath(fname, dldir, ".temp");
  792.     sprintf(command,"%s %s", pager, fname);
  793. #ifdef __SASC
  794.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  795. #else
  796.     SetMode(_devtab[fileno(stdin)].fd,0L);
  797. #endif
  798.     System(command,0L);
  799. #ifdef __SASC
  800.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  801. #else
  802.     SetMode(_devtab[fileno(stdin)].fd,1L);
  803. #endif
  804.  
  805. }
  806.  
  807. jmp_buf    recvabort;
  808.  
  809. abortrecv()
  810. {
  811.  
  812.     mflag = 0;
  813.     abrtflag = 0;
  814.     printf("\n");
  815.     (void) fflush(stdout);
  816.     longjmp(recvabort, 1);
  817. }
  818.  
  819. recvrequest(cmd, local, remote, mode, printnames)
  820.     char *cmd, *local, *remote, *mode;
  821. {
  822.     FILE *fout;
  823.     int din;
  824.     int (*closefunc)(), fclose();
  825. //    sig_t (*oldintr)(), (*oldintp)();
  826.     int abortrecv();
  827.     int oldverbose, oldtype = 0, is_retr, tcrflag, nfnd, bare_lfs = 0;
  828.     char *gunique(), msg;
  829.     static char *buf;
  830.     static int bufsize;
  831.     long bytes = 0, hashbytes = HASHBYTES;
  832.     struct fd_set mask;
  833.     register int c, d;
  834.     struct timeval start, stop;
  835.     struct stat st;
  836.     char str_buf[16];
  837.     extern char *malloc();
  838.     char real_local[128];
  839.  
  840.     if (local[0] != '-')
  841.     {    joinpath (real_local, dldir, basename(local));
  842.         local = real_local;
  843.     }
  844.  
  845.     is_retr = strcmp(cmd, "RETR") == 0;
  846.     if (is_retr && verbose && printnames) {
  847.         if (local && *local != '-')
  848.             printf("local: %s ", local);
  849.         if (remote)
  850.             printf("remote: %s\n", remote);
  851.     }
  852.     if (proxy && is_retr) {
  853.         proxtrans(cmd, local, remote);
  854.         return;
  855.     }
  856.     closefunc = NULL;
  857. //    oldintr = NULL;
  858. //    oldintp = NULL;
  859.     tcrflag = !crflag && is_retr;
  860.     if (setjmp(recvabort)) {
  861.         while (cpend) {
  862.             (void) getreply(0);
  863.         }
  864.         if (data >= 0) {
  865.             (void) s_close(data);
  866.             data = -1;
  867.         }
  868. //        if (oldintr)
  869. //            (void) signal(SIGINT, oldintr);
  870.         code = -1;
  871.         return;
  872.     }
  873. //    oldintr = signal(SIGINT, abortrecv);
  874.     if (strcmp(local, "-") && *local != '|') {
  875.         if (access(local, 2) < 0) {
  876.             char *dir = rindex(local, '/');
  877.  
  878. #ifdef AZTEC_C
  879.             /* Aztec's errors are different from those in net includes */
  880.             if (errno != 1 /*ENOENT*/ && errno != 10 /*EACCES*/)
  881. #else
  882.             if (errno != ENOENT && errno != EACCES)
  883. #endif
  884.             {    perror(local);
  885. //                (void) signal(SIGINT, oldintr);
  886.                 code = -1;
  887.                 return;
  888.             }
  889.             if (dir != NULL)
  890.                 *dir = 0;
  891.             if (dir != NULL)
  892.                 *dir = '/';
  893.             if (!runique && errno == EACCES) {
  894.                 perror(local);
  895. //                (void) signal(SIGINT, oldintr);
  896.                 code = -1;
  897.                 return;
  898.             }
  899.         }
  900.         else if (runique && (local = gunique(local)) == NULL) {
  901. //            (void) signal(SIGINT, oldintr);
  902.             code = -1;
  903.             return;
  904.         }
  905.     }
  906.     if (initconn()) {
  907. //        (void) signal(SIGINT, oldintr);
  908.         code = -1;
  909.         return;
  910.     }
  911.     if (setjmp(recvabort))
  912.         goto abort;
  913.  
  914. #ifdef __SASC
  915.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  916. #else
  917.     SetMode(_devtab[fileno(stdin)].fd,1L);
  918. #endif
  919.     Enable_Abort = 0;
  920.  
  921.     if (!is_retr) {
  922.         if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
  923.             oldtype = type;
  924.             oldverbose = verbose;
  925.             if (!debug)
  926.                 verbose = 0;
  927.             setascii();
  928.             verbose = oldverbose;
  929.         }
  930.     } else if (restart_point) {
  931.         if (command("REST %ld", (long) restart_point) != CONTINUE)
  932.             {
  933. #ifdef __SASC
  934.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  935. #else
  936.             SetMode(_devtab[fileno(stdin)].fd,0L);
  937. #endif
  938.             Enable_Abort = 1;
  939.             return;
  940.             }
  941.     }
  942.     if (remote) {
  943.         if (command("%s %s", cmd, remote) != PRELIM) {
  944. //            (void) signal(SIGINT, oldintr);
  945.             if (oldtype) {
  946.                 if (!debug)
  947.                     verbose = 0;
  948.                 switch (oldtype) {
  949.                     case TYPE_I:
  950.                         setbinary();
  951.                         break;
  952.                     case TYPE_E:
  953.                         setebcdic();
  954.                         break;
  955.                     case TYPE_L:
  956.                         settenex();
  957.                         break;
  958.                 }
  959.                 verbose = oldverbose;
  960.             }
  961. #ifdef __SASC
  962.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  963. #else
  964.             SetMode(_devtab[fileno(stdin)].fd,0L);
  965. #endif
  966.             Enable_Abort = 1;
  967.             return;
  968.         }
  969.     } else {
  970.         if (command("%s", cmd) != PRELIM) {
  971. //            (void) signal(SIGINT, oldintr);
  972.             if (oldtype) {
  973.                 if (!debug)
  974.                     verbose = 0;
  975.                 switch (oldtype) {
  976.                     case TYPE_I:
  977.                         setbinary();
  978.                         break;
  979.                     case TYPE_E:
  980.                         setebcdic();
  981.                         break;
  982.                     case TYPE_L:
  983.                         settenex();
  984.                         break;
  985.                 }
  986.                 verbose = oldverbose;
  987.             }
  988. #ifdef __SASC
  989.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  990. #else
  991.             SetMode(_devtab[fileno(stdin)].fd,0L);
  992. #endif
  993.             Enable_Abort = 1;
  994.             return;
  995.         }
  996.     }
  997.     din = dataconn("r");
  998.     if (din == -1)
  999.         goto abort;
  1000.     if (strcmp(local, "-") == 0)
  1001.     {    joinpath(real_local, dldir, ".temp");
  1002.         fout = fopen(real_local,"w");
  1003.         if (fout == NULL) {
  1004.             perror(local);
  1005.             goto abort;
  1006.         }
  1007.         closefunc = display_temp;
  1008.     }
  1009. #if 0
  1010.     else if (*local == '|') {
  1011.         oldintp = signal(SIGPIPE, SIG_IGN);
  1012.         fout = popen(local + 1, "w");
  1013.         if (fout == NULL) {
  1014.             perror(local+1);
  1015.             goto abort;
  1016.         }
  1017.         closefunc = pclose;
  1018.     }
  1019. #endif
  1020.     else
  1021.     {    fout = fopen(local, mode);
  1022.         if (fout == NULL) {
  1023.             perror(local);
  1024.             goto abort;
  1025.         }
  1026.         closefunc = fclose;
  1027.     }
  1028. #if 0
  1029.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  1030.         st.st_blksize = BUFSIZ;
  1031.     if (st.st_blksize > bufsize) {
  1032.         if (buf)
  1033.             (void) free(buf);
  1034.         buf = malloc((unsigned)st.st_blksize);
  1035.         if (buf == NULL) {
  1036.             perror("malloc");
  1037.             bufsize = 0;
  1038.             goto abort;
  1039.         }
  1040.         bufsize = st.st_blksize;
  1041.     }
  1042. #else
  1043.     if (BUFSIZ > bufsize) {
  1044.         if (buf)
  1045.             free(buf);
  1046.         buf = malloc(BUFSIZ);
  1047.         if (buf == NULL) {
  1048.             perror("malloc");
  1049.             bufsize = 0;
  1050.             goto abort;
  1051.         }
  1052.         bufsize = BUFSIZ;
  1053.     }
  1054. #endif
  1055.     (void) mygettimeofday(&start, (struct timezone *)0);
  1056.     switch (type) {
  1057.  
  1058.     case TYPE_A:
  1059.     case TYPE_I:
  1060.     case TYPE_L:
  1061.         if (restart_point &&
  1062.             lseek(fileno(fout), (long) restart_point, 0) < 0) {
  1063.             perror(local);
  1064.             if (closefunc != NULL)
  1065.                 (*closefunc)(fout);
  1066. #ifdef __SASC
  1067.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1068. #else
  1069.             SetMode(_devtab[fileno(stdin)].fd,0L);
  1070. #endif
  1071.             Enable_Abort = 1;
  1072.             return;
  1073.         }
  1074.         errno = d = 0;
  1075.         while ((c = recv(din, buf, bufsize, 0)) > 0) {
  1076.             if ((d = write(fileno(fout), buf, c)) != c)
  1077.                 break;
  1078.             bytes += c;
  1079.             if (hash) {
  1080.                 while (bytes >= hashbytes) {
  1081.                     (void) putchar('#');
  1082.                     hashbytes += HASHBYTES;
  1083.                 }
  1084.                 (void) fflush(stdout);
  1085.             }
  1086. #ifdef __SASC
  1087.             if (WaitForChar(chkufb(fileno(stdin))->ufbfh, 0L) == DOSTRUE)
  1088. #else
  1089.             if (WaitForChar(_devtab[fileno(stdin)].fd, 0L) == DOSTRUE)
  1090. #endif
  1091.                 goto abort;
  1092.             if (SetSignal (0L,SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) goto abort;
  1093.         }
  1094.         if (hash && bytes > 0) {
  1095.             if (bytes < HASHBYTES)
  1096.                 (void) putchar('#');
  1097.             (void) putchar('\n');
  1098.             (void) fflush(stdout);
  1099.         }
  1100.         if (c < 0) {
  1101.             if (errno != EPIPE)
  1102.                 perror("netin");
  1103.             bytes = -1;
  1104.         }
  1105.         if (d < c) {
  1106.             if (d < 0)
  1107.                 perror(local);
  1108.             else
  1109.                 fprintf(stderr, "%s: short write\n", local);
  1110.         }
  1111.         break;
  1112.  
  1113. #if 0
  1114.     case TYPE_A:
  1115.         if (restart_point) {
  1116.             register int i, n, c;
  1117.  
  1118.             if (fseek(fout, 0L, L_SET) < 0)
  1119.                 goto done;
  1120.             n = restart_point;
  1121.             i = 0;
  1122.             while (i++ < n) {
  1123.                 if ((c=getc(fout)) == EOF)
  1124.                     goto done;
  1125.                 if (c == '\n')
  1126.                     i++;
  1127.             }
  1128.             if (fseek(fout, 0L, L_INCR) < 0) {
  1129. done:
  1130.                 perror(local);
  1131.                 if (closefunc != NULL)
  1132.                     (*closefunc)(fout);
  1133.                 return;
  1134.             }
  1135.         }
  1136.         while ((c = getc(din)) != EOF) {
  1137.             if (c == '\n')
  1138.                 bare_lfs++;
  1139.             while (c == '\r') {
  1140.                 while (hash && (bytes >= hashbytes)) {
  1141.                     (void) putchar('#');
  1142.                     (void) fflush(stdout);
  1143.                     hashbytes += HASHBYTES;
  1144.                 }
  1145.                 bytes++;
  1146.                 if ((c = getc(din)) != '\n' || tcrflag) {
  1147.                     if (ferror(fout))
  1148.                         goto break2;
  1149.                     (void) putc('\r', fout);
  1150.                     if (c == '\0') {
  1151.                         bytes++;
  1152.                         goto contin2;
  1153.                     }
  1154.                     if (c == EOF)
  1155.                         goto contin2;
  1156.                 }
  1157.             }
  1158.             (void) putc(c, fout);
  1159.             bytes++;
  1160.     contin2:    ;
  1161.         }
  1162. break2:
  1163.         if (bare_lfs) {
  1164.             printf("WARNING! %d bare linefeeds received in ASCII mode\n");
  1165.             printf("File may not have transferred correctly.\n");
  1166.         }
  1167.         if (hash) {
  1168.             if (bytes < hashbytes)
  1169.                 (void) putchar('#');
  1170.             (void) putchar('\n');
  1171.             (void) fflush(stdout);
  1172.         }
  1173.         if (ferror(din)) {
  1174.             if (errno != EPIPE)
  1175.                 perror("netin");
  1176.             bytes = -1;
  1177.         }
  1178.         if (ferror(fout))
  1179.             perror(local);
  1180.         break;
  1181. #endif
  1182.     }
  1183.  
  1184.     if (closefunc != NULL)
  1185.         (*closefunc)(fout);
  1186. //    (void) signal(SIGINT, oldintr);
  1187. //    if (oldintp)
  1188. //        (void) signal(SIGPIPE, oldintp);
  1189.     (void) mygettimeofday(&stop, (struct timezone *)0);
  1190.     (void) s_close (din);
  1191.     (void) getreply(0);
  1192.  
  1193. #ifdef __SASC
  1194.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1195. #else
  1196.     SetMode(_devtab[fileno(stdin)].fd,0L);
  1197. #endif
  1198.     Enable_Abort = 1;
  1199.  
  1200.     if (bytes > 0)
  1201. #ifdef FTP_LOG_USAGE
  1202.         ptransfer("received", bytes, &start, &stop, remote);
  1203. #else
  1204.     {   ptransfer("received", bytes, &start, &stop);
  1205.         fprintf(log_file,"%s %d\n",hostname, bytes);
  1206.     }
  1207. #endif /* FTP_LOG_USAGE */
  1208.     if (oldtype) {
  1209.         if (!debug)
  1210.             verbose = 0;
  1211.         switch (oldtype) {
  1212.             case TYPE_I:
  1213.                 setbinary();
  1214.                 break;
  1215.             case TYPE_E:
  1216.                 setebcdic();
  1217.                 break;
  1218.             case TYPE_L:
  1219.                 settenex();
  1220.                 break;
  1221.         }
  1222.         verbose = oldverbose;
  1223.     }
  1224.     return;
  1225. abort:
  1226. /* abort using RFC959 recommended IP,SYNC sequence  */
  1227.  
  1228.     (void) mygettimeofday(&stop, (struct timezone *)0);
  1229. //    if (oldintp)
  1230. //        (void) signal(SIGPIPE, oldintr);
  1231. //    (void) signal(SIGINT,SIG_IGN);
  1232.     if (oldtype) {
  1233.         if (!debug)
  1234.             verbose = 0;
  1235.         switch (oldtype) {
  1236.             case TYPE_I:
  1237.                 setbinary();
  1238.                 break;
  1239.             case TYPE_E:
  1240.                 setebcdic();
  1241.                 break;
  1242.             case TYPE_L:
  1243.                 settenex();
  1244.                 break;
  1245.         }
  1246.         verbose = oldverbose;
  1247.     }
  1248.     if (!cpend) {
  1249.         code = -1;
  1250. //        (void) signal(SIGINT,oldintr);
  1251.         return;
  1252.     }
  1253.  
  1254.     str_buf[0] = IAC; str_buf[1] = IP;
  1255.     send(cout, str_buf, 2, 0);
  1256.     str_buf[0] = IAC; str_buf[1] = DM;
  1257. /* send IAC in urgent mode instead of DM because UNIX places oob mark */
  1258. /* after urgent byte rather than before as now is protocol            */
  1259. #if 0
  1260.     if (send(cout,str_buf,2,MSG_OOB) != 2) {
  1261.         perror("abort");
  1262.     }
  1263. #endif
  1264.     sprintf(str_buf,"ABOR\r\n");
  1265.     send(cout, str_buf, 6, 0);
  1266.     FD_ZERO(&mask);
  1267.     FD_SET(cin, &mask);
  1268.     if (din) { 
  1269.         FD_SET(din, &mask);
  1270.     }
  1271.     if ((nfnd = empty(&mask,10)) <= 0) {
  1272.         if (nfnd < 0) {
  1273.             perror("abort");
  1274.         }
  1275.         code = -1;
  1276.         lostpeer();
  1277.     }
  1278.     if (din && FD_ISSET(din, &mask)) {
  1279.         while ((c = read(din, buf, bufsize)) > 0)
  1280.             ;
  1281.     }
  1282.     if (data >= 0) {
  1283.         (void) s_close(data);
  1284.         data = -1;
  1285.     }
  1286.     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
  1287.         (void) getreply(0);
  1288.     }
  1289.     (void) getreply(0);
  1290.     code = -1;
  1291.  
  1292.     if (closefunc != NULL && fout != NULL)
  1293.         (*closefunc)(fout);
  1294.  
  1295. #ifdef __SASC
  1296.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1297. #else
  1298.     SetMode(_devtab[fileno(stdin)].fd,0L);
  1299. #endif
  1300.     Enable_Abort = 1;
  1301.  
  1302.     if (bytes > 0)
  1303. #ifdef FTP_LOG_USAGE
  1304.         ptransfer("received", bytes, &start, &stop, remote);
  1305. #else
  1306.     {   ptransfer("received", bytes, &start, &stop);
  1307.         fprintf(log_file,"%s %d\n",hostname, bytes);
  1308.     }
  1309. #endif /* FTP_LOG_USAGE */
  1310. //    (void) signal(SIGINT,oldintr);
  1311. }
  1312.  
  1313. /*
  1314.  * Need to start a listen on the data channel
  1315.  * before we send the command, otherwise the
  1316.  * server's connect may fail.
  1317.  */
  1318. int sendport = -1;
  1319.  
  1320. initconn()
  1321. {
  1322.     register char *p, *a;
  1323.     int result, len, tmpno = 0;
  1324.     int on = 1;
  1325.  
  1326. noport:
  1327.     data_addr = myctladdr;
  1328.     if (sendport)
  1329.         data_addr.sin_port = 0;    /* let system pick one */ 
  1330.     if (data != -1)
  1331.         (void) s_close (data);
  1332.     data = socket(AF_INET, SOCK_STREAM, 0);
  1333.     if (data < 0) {
  1334.         perror("ftp: socket");
  1335.         if (tmpno)
  1336.             sendport = 1;
  1337.         return (1);
  1338.     }
  1339.     if (!sendport)
  1340.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1341.             perror("ftp: setsockopt (reuse address)");
  1342.             goto bad;
  1343.         }
  1344.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1345.         perror("ftp: bind");
  1346.         goto bad;
  1347.     }
  1348.     if (options & SO_DEBUG &&
  1349.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1350.         perror("ftp: setsockopt (ignored)");
  1351.     len = sizeof (data_addr);
  1352.     if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1353.         perror("ftp: getsockname");
  1354.         goto bad;
  1355.     }
  1356.     if (listen(data, 1) < 0)
  1357.         perror("ftp: listen");
  1358.     if (sendport) {
  1359.         a = (char *)&data_addr.sin_addr;
  1360.         p = (char *)&data_addr.sin_port;
  1361. #define    UC(b)    (((int)b)&0xff)
  1362.         result =
  1363.             command("PORT %d,%d,%d,%d,%d,%d",
  1364.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1365.               UC(p[0]), UC(p[1]));
  1366.         if (result == ERROR && sendport == -1) {
  1367.             sendport = 0;
  1368.             tmpno = 1;
  1369.             goto noport;
  1370.         }
  1371.         return (result != COMPLETE);
  1372.     }
  1373.     if (tmpno)
  1374.         sendport = 1;
  1375.     return (0);
  1376. bad:
  1377.     (void) s_close(data), data = -1;
  1378.     if (tmpno)
  1379.         sendport = 1;
  1380.     return (1);
  1381. }
  1382.  
  1383. dataconn(mode)
  1384.     char *mode;
  1385. {
  1386.     struct sockaddr_in from;
  1387.     int s, fromlen = sizeof (from);
  1388.  
  1389.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1390.     if (s < 0) {
  1391.         perror("ftp: accept");
  1392.         (void) s_close(data), data = -1;
  1393.         return -1;
  1394.     }
  1395.     (void) s_close(data);
  1396.     data = s;
  1397.     return data;
  1398. }
  1399.  
  1400. #ifdef FTP_LOG_USAGE
  1401. ptransfer(direction, bytes, t0, t1, filename)
  1402. #else
  1403. ptransfer(direction, bytes, t0, t1)
  1404. #endif /* FTP_LOG_USAGE */
  1405.     char *direction;
  1406.     long bytes;
  1407.     struct timeval *t0, *t1;
  1408. #ifdef FTP_LOG_USAGE
  1409.         char *filename;
  1410. #endif /* FTP_LOG_USAGE */
  1411. {
  1412.     struct timeval td;
  1413.     float s, bs;
  1414.  
  1415.     if (verbose) {
  1416.         tvsub(&td, t1, t0);
  1417.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1418. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1419.         bs = bytes / nz(s);
  1420.         printf("%ld bytes %s in %.2f seconds (%.2f Kbytes/s)\n",
  1421.             bytes, direction, s, bs / 1024.);
  1422. #ifdef FTP_LOG_USAGE
  1423.         syslog(LOG_INFO, "%s (%ld bytes) %s\n", filename, bytes, direction);
  1424. #endif /* FTP_LOG_USAGE */
  1425.     }
  1426. }
  1427.  
  1428. /*tvadd(tsum, t0)
  1429.     struct timeval *tsum, *t0;
  1430. {
  1431.  
  1432.     tsum->tv_sec += t0->tv_sec;
  1433.     tsum->tv_usec += t0->tv_usec;
  1434.     if (tsum->tv_usec > 1000000)
  1435.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1436. } */
  1437.  
  1438. tvsub(tdiff, t1, t0)
  1439.     struct timeval *tdiff, *t1, *t0;
  1440. {
  1441.  
  1442.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1443.     if (t1->tv_usec < t0->tv_usec)
  1444.     {    t1->tv_usec += 1000000;
  1445.         tdiff->tv_sec--;
  1446.     }
  1447.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1448. }
  1449.  
  1450. sig_t
  1451. psabort()
  1452. {
  1453.     extern int abrtflag;
  1454.  
  1455.     abrtflag++;
  1456. }
  1457.  
  1458. pswitch(flag)
  1459.     int flag;
  1460. {
  1461. #if 0
  1462.     extern int proxy, abrtflag;
  1463.     sig_t (*oldintr)();
  1464.     static struct comvars {
  1465.         int connect;
  1466.         char name[MAXHOSTNAMELEN];
  1467.         struct sockaddr_in mctl;
  1468.         struct sockaddr_in hctl;
  1469.         FILE *in;
  1470.         FILE *out;
  1471.         int tpe;
  1472.         int cpnd;
  1473.         int sunqe;
  1474.         int runqe;
  1475.         int mcse;
  1476.         int ntflg;
  1477.         char nti[17];
  1478.         char nto[17];
  1479.         int mapflg;
  1480.         char mi[MAXPATHLEN];
  1481.         char mo[MAXPATHLEN];
  1482.         } proxstruct, tmpstruct;
  1483.     struct comvars *ip, *op;
  1484.  
  1485.     abrtflag = 0;
  1486.     oldintr = signal(SIGINT, psabort);
  1487.     if (flag) {
  1488.         if (proxy)
  1489.             return;
  1490.         ip = &tmpstruct;
  1491.         op = &proxstruct;
  1492.         proxy++;
  1493.     }
  1494.     else {
  1495.         if (!proxy)
  1496.             return;
  1497.         ip = &proxstruct;
  1498.         op = &tmpstruct;
  1499.         proxy = 0;
  1500.     }
  1501.     ip->connect = connected;
  1502.     connected = op->connect;
  1503.     if (hostname) {
  1504.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1505.         ip->name[strlen(ip->name)] = '\0';
  1506.     } else
  1507.         ip->name[0] = 0;
  1508.     hostname = op->name;
  1509.     ip->hctl = hisctladdr;
  1510.     hisctladdr = op->hctl;
  1511.     ip->mctl = myctladdr;
  1512.     myctladdr = op->mctl;
  1513. //    ip->in = cin;
  1514. //    cin = op->in;
  1515. //    ip->out = cout;
  1516. //    cout = op->out;
  1517.     ip->tpe = type;
  1518.     type = op->tpe;
  1519.     if (!type)
  1520.         type = 1;
  1521.     ip->cpnd = cpend;
  1522.     cpend = op->cpnd;
  1523.     ip->sunqe = sunique;
  1524.     sunique = op->sunqe;
  1525.     ip->runqe = runique;
  1526.     runique = op->runqe;
  1527.     ip->mcse = mcase;
  1528.     mcase = op->mcse;
  1529.     ip->ntflg = ntflag;
  1530.     ntflag = op->ntflg;
  1531.     (void) strncpy(ip->nti, ntin, 16);
  1532.     (ip->nti)[strlen(ip->nti)] = '\0';
  1533.     (void) strcpy(ntin, op->nti);
  1534.     (void) strncpy(ip->nto, ntout, 16);
  1535.     (ip->nto)[strlen(ip->nto)] = '\0';
  1536.     (void) strcpy(ntout, op->nto);
  1537.     ip->mapflg = mapflag;
  1538.     mapflag = op->mapflg;
  1539.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1540.     (ip->mi)[strlen(ip->mi)] = '\0';
  1541.     (void) strcpy(mapin, op->mi);
  1542.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1543.     (ip->mo)[strlen(ip->mo)] = '\0';
  1544.     (void) strcpy(mapout, op->mo);
  1545.     (void) signal(SIGINT, oldintr);
  1546.     if (abrtflag) {
  1547.         abrtflag = 0;
  1548.         (*oldintr)();
  1549.     }
  1550. #endif
  1551. }
  1552.  
  1553. jmp_buf ptabort;
  1554. int ptabflg;
  1555.  
  1556. sig_t
  1557. abortpt()
  1558. {
  1559.     printf("\n");
  1560.     (void) fflush(stdout);
  1561.     ptabflg++;
  1562.     mflag = 0;
  1563.     abrtflag = 0;
  1564.     longjmp(ptabort, 1);
  1565. }
  1566.  
  1567. proxtrans(cmd, local, remote)
  1568.     char *cmd, *local, *remote;
  1569. {
  1570. #if 0
  1571.     sig_t (*oldintr)(), abortpt();
  1572.     int tmptype, oldtype = 0, secndflag = 0, nfnd;
  1573.     extern jmp_buf ptabort;
  1574.     char *cmd2;
  1575.     struct fd_set mask;
  1576.  
  1577.     if (strcmp(cmd, "RETR"))
  1578.         cmd2 = "RETR";
  1579.     else
  1580.         cmd2 = runique ? "STOU" : "STOR";
  1581.     if (command("PASV") != COMPLETE) {
  1582.         printf("proxy server does not support third part transfers.\n");
  1583.         return;
  1584.     }
  1585.     tmptype = type;
  1586.     pswitch(0);
  1587.     if (!connected) {
  1588.         printf("No primary connection\n");
  1589.         pswitch(1);
  1590.         code = -1;
  1591.         return;
  1592.     }
  1593.     if (type != tmptype) {
  1594.         oldtype = type;
  1595.         switch (tmptype) {
  1596.             case TYPE_A:
  1597.                 setascii();
  1598.                 break;
  1599.             case TYPE_I:
  1600.                 setbinary();
  1601.                 break;
  1602.             case TYPE_E:
  1603.                 setebcdic();
  1604.                 break;
  1605.             case TYPE_L:
  1606.                 settenex();
  1607.                 break;
  1608.         }
  1609.     }
  1610.     if (command("PORT %s", pasv) != COMPLETE) {
  1611.         switch (oldtype) {
  1612.             case 0:
  1613.                 break;
  1614.             case TYPE_A:
  1615.                 setascii();
  1616.                 break;
  1617.             case TYPE_I:
  1618.                 setbinary();
  1619.                 break;
  1620.             case TYPE_E:
  1621.                 setebcdic();
  1622.                 break;
  1623.             case TYPE_L:
  1624.                 settenex();
  1625.                 break;
  1626.         }
  1627.         pswitch(1);
  1628.         return;
  1629.     }
  1630.     if (setjmp(ptabort))
  1631.         goto abort;
  1632.     oldintr = signal(SIGINT, abortpt);
  1633.     if (command("%s %s", cmd, remote) != PRELIM) {
  1634.         (void) signal(SIGINT, oldintr);
  1635.         switch (oldtype) {
  1636.             case 0:
  1637.                 break;
  1638.             case TYPE_A:
  1639.                 setascii();
  1640.                 break;
  1641.             case TYPE_I:
  1642.                 setbinary();
  1643.                 break;
  1644.             case TYPE_E:
  1645.                 setebcdic();
  1646.                 break;
  1647.             case TYPE_L:
  1648.                 settenex();
  1649.                 break;
  1650.         }
  1651.         pswitch(1);
  1652.         return;
  1653.     }
  1654.     Delay(100L);
  1655.     pswitch(1);
  1656.     secndflag++;
  1657.     if (command("%s %s", cmd2, local) != PRELIM)
  1658.         goto abort;
  1659.     ptflag++;
  1660.     (void) getreply(0);
  1661.     pswitch(0);
  1662.     (void) getreply(0);
  1663.     (void) signal(SIGINT, oldintr);
  1664.     switch (oldtype) {
  1665.         case 0:
  1666.             break;
  1667.         case TYPE_A:
  1668.             setascii();
  1669.             break;
  1670.         case TYPE_I:
  1671.             setbinary();
  1672.             break;
  1673.         case TYPE_E:
  1674.             setebcdic();
  1675.             break;
  1676.         case TYPE_L:
  1677.             settenex();
  1678.             break;
  1679.     }
  1680.     pswitch(1);
  1681.     ptflag = 0;
  1682.     printf("local: %s remote: %s\n", local, remote);
  1683.     return;
  1684. abort:
  1685.     (void) signal(SIGINT, SIG_IGN);
  1686.     ptflag = 0;
  1687.     if (strcmp(cmd, "RETR") && !proxy)
  1688.         pswitch(1);
  1689.     else if (!strcmp(cmd, "RETR") && proxy)
  1690.         pswitch(0);
  1691.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1692.         if (command("%s %s", cmd2, local) != PRELIM) {
  1693.             pswitch(0);
  1694.             switch (oldtype) {
  1695.                 case 0:
  1696.                     break;
  1697.                 case TYPE_A:
  1698.                     setascii();
  1699.                     break;
  1700.                 case TYPE_I:
  1701.                     setbinary();
  1702.                     break;
  1703.                 case TYPE_E:
  1704.                     setebcdic();
  1705.                     break;
  1706.                 case TYPE_L:
  1707.                     settenex();
  1708.                     break;
  1709.             }
  1710.             if (cpend) {
  1711.                 char msg[2];
  1712.  
  1713.                 fprintf(cout,"%c%c",IAC,IP);
  1714.                 (void) fflush(cout); 
  1715.                 *msg = IAC;
  1716.                 *(msg+1) = DM;
  1717.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1718.                     perror("abort");
  1719.                 fprintf(cout,"ABOR\r\n");
  1720.                 (void) fflush(cout);
  1721.                 FD_ZERO(&mask);
  1722.                 FD_SET(fileno(cin), &mask);
  1723.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1724.                     if (nfnd < 0) {
  1725.                         perror("abort");
  1726.                     }
  1727.                     if (ptabflg)
  1728.                         code = -1;
  1729.                     lostpeer();
  1730.                 }
  1731.                 (void) getreply(0);
  1732.                 (void) getreply(0);
  1733.             }
  1734.         }
  1735.         pswitch(1);
  1736.         if (ptabflg)
  1737.             code = -1;
  1738.         (void) signal(SIGINT, oldintr);
  1739.         return;
  1740.     }
  1741.     if (cpend) {
  1742.         char msg[2];
  1743.  
  1744.         fprintf(cout,"%c%c",IAC,IP);
  1745.         (void) fflush(cout); 
  1746.         *msg = IAC;
  1747.         *(msg+1) = DM;
  1748.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1749.             perror("abort");
  1750.         fprintf(cout,"ABOR\r\n");
  1751.         (void) fflush(cout);
  1752.         FD_ZERO(&mask);
  1753.         FD_SET(fileno(cin), &mask);
  1754.         if ((nfnd = empty(&mask,10)) <= 0) {
  1755.             if (nfnd < 0) {
  1756.                 perror("abort");
  1757.             }
  1758.             if (ptabflg)
  1759.                 code = -1;
  1760.             lostpeer();
  1761.         }
  1762.         (void) getreply(0);
  1763.         (void) getreply(0);
  1764.     }
  1765.     pswitch(!proxy);
  1766.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1767.         if (command("%s %s", cmd2, local) != PRELIM) {
  1768.             pswitch(0);
  1769.             switch (oldtype) {
  1770.                 case 0:
  1771.                     break;
  1772.                 case TYPE_A:
  1773.                     setascii();
  1774.                     break;
  1775.                 case TYPE_I:
  1776.                     setbinary();
  1777.                     break;
  1778.                 case TYPE_E:
  1779.                     setebcdic();
  1780.                     break;
  1781.                 case TYPE_L:
  1782.                     settenex();
  1783.                     break;
  1784.             }
  1785.             if (cpend) {
  1786.                 char msg[2];
  1787.  
  1788.                 fprintf(cout,"%c%c",IAC,IP);
  1789.                 (void) fflush(cout); 
  1790.                 *msg = IAC;
  1791.                 *(msg+1) = DM;
  1792.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1793.                     perror("abort");
  1794.                 fprintf(cout,"ABOR\r\n");
  1795.                 (void) fflush(cout);
  1796.                 FD_ZERO(&mask);
  1797.                 FD_SET(fileno(cin), &mask);
  1798.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1799.                     if (nfnd < 0) {
  1800.                         perror("abort");
  1801.                     }
  1802.                     if (ptabflg)
  1803.                         code = -1;
  1804.                     lostpeer();
  1805.                 }
  1806.                 (void) getreply(0);
  1807.                 (void) getreply(0);
  1808.             }
  1809.             pswitch(1);
  1810.             if (ptabflg)
  1811.                 code = -1;
  1812.             (void) signal(SIGINT, oldintr);
  1813.             return;
  1814.         }
  1815.     }
  1816.     if (cpend) {
  1817.         char msg[2];
  1818.  
  1819.         fprintf(cout,"%c%c",IAC,IP);
  1820.         (void) fflush(cout); 
  1821.         *msg = IAC;
  1822.         *(msg+1) = DM;
  1823.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1824.             perror("abort");
  1825.         fprintf(cout,"ABOR\r\n");
  1826.         (void) fflush(cout);
  1827.         FD_ZERO(&mask);
  1828.         FD_SET(fileno(cin), &mask);
  1829.         if ((nfnd = empty(&mask,10)) <= 0) {
  1830.             if (nfnd < 0) {
  1831.                 perror("abort");
  1832.             }
  1833.             if (ptabflg)
  1834.                 code = -1;
  1835.             lostpeer();
  1836.         }
  1837.         (void) getreply(0);
  1838.         (void) getreply(0);
  1839.     }
  1840.     pswitch(!proxy);
  1841.     if (cpend) {
  1842.         FD_ZERO(&mask);
  1843.         FD_SET(fileno(cin), &mask);
  1844.         if ((nfnd = empty(&mask,10)) <= 0) {
  1845.             if (nfnd < 0) {
  1846.                 perror("abort");
  1847.             }
  1848.             if (ptabflg)
  1849.                 code = -1;
  1850.             lostpeer();
  1851.         }
  1852.         (void) getreply(0);
  1853.         (void) getreply(0);
  1854.     }
  1855.     if (proxy)
  1856.         pswitch(0);
  1857.     switch (oldtype) {
  1858.         case 0:
  1859.             break;
  1860.         case TYPE_A:
  1861.             setascii();
  1862.             break;
  1863.         case TYPE_I:
  1864.             setbinary();
  1865.             break;
  1866.         case TYPE_E:
  1867.             setebcdic();
  1868.             break;
  1869.         case TYPE_L:
  1870.             settenex();
  1871.             break;
  1872.     }
  1873.     pswitch(1);
  1874.     if (ptabflg)
  1875.         code = -1;
  1876.     (void) signal(SIGINT, oldintr);
  1877. #endif
  1878. }
  1879.  
  1880. reset()
  1881. {
  1882.     struct fd_set mask;
  1883.     int nfnd = 1;
  1884.  
  1885.     FD_ZERO(&mask);
  1886.     while (nfnd > 0) {
  1887.         FD_SET(cin, &mask);
  1888.         if ((nfnd = empty(&mask,0)) < 0) {
  1889.             perror("reset");
  1890.             code = -1;
  1891.             lostpeer();
  1892.         }
  1893.         else if (nfnd) {
  1894.             (void) getreply(0);
  1895.         }
  1896.     }
  1897. }
  1898.  
  1899. char *
  1900. gunique(local)
  1901.     char *local;
  1902. {
  1903.     static char new[MAXPATHLEN];
  1904.     char *cp = rindex(local, '/');
  1905.     int d, count=0;
  1906.     char ext = '1';
  1907.  
  1908.     if (cp)
  1909.         *cp = '\0';
  1910.     d = access(cp ? local : ".", 2);
  1911.     if (cp)
  1912.         *cp = '/';
  1913.     if (d < 0) {
  1914.         perror(local);
  1915.         return((char *) 0);
  1916.     }
  1917.     (void) strcpy(new, local);
  1918.     cp = new + strlen(new);
  1919.     *cp++ = '.';
  1920.     while (!d) {
  1921.         if (++count == 100) {
  1922.             printf("runique: can't find unique file name.\n");
  1923.             return((char *) 0);
  1924.         }
  1925.         *cp++ = ext;
  1926.         *cp = '\0';
  1927.         if (ext == '9')
  1928.             ext = '0';
  1929.         else
  1930.             ext++;
  1931.         if ((d = access(new, 0)) < 0)
  1932.             break;
  1933.         if (ext != '0')
  1934.             cp--;
  1935.         else if (*(cp - 2) == '.')
  1936.             *(cp - 1) = '1';
  1937.         else {
  1938.             *(cp - 2) = *(cp - 2) + 1;
  1939.             cp--;
  1940.         }
  1941.     }
  1942.     return(new);
  1943. }
  1944.